﻿#include "appmanager.h"
#include "ui_appmanager.h"
#include "appline.h"



/*
 * 版本记录表
 * v1.6(2024/11/26)
 * 1. 增加Qt6兼容
 * 2. 新增重新导入程序关闭前所管理的程序的运行状态
 * 3. 修改进程启动逻辑，通过函数递归进行启动，解决进程名相同时按钮关联错误的问题
 * 4. 修改进程关闭逻辑，使用QProcess的start替代QProcess::execute执行taskkill命令,原因为：Qt6时taskkill命令执行的权限被限制
 * 5. 修改关闭窗口的实现逻辑，不在弹出对话框，直接隐藏到系统托盘
 * 6. 修改界面ToolButton的打开默认路径，如果LineEdit控件中有有效路径，则打开改有效路径
 *
 * v1.7(2024/12/02)
 * 1. 修复点击打开本页时，如果本页程序未全部打开切换tab时，打开了其他tab页中相同位置的程序问题
 *
 * v1.8(2024/12/10)
 * 1. 增加标签页拖拽功能
 * 2. 解决删除应用程序行和删除当前标签页时程序崩溃问题
 * 3. 修改系统托盘启动时间，去除程序启动时添加系统托盘，只在点击窗口关闭按钮后启动系统托盘
 *
 * v1.9(2024/12/12)
 * 1. 将行控件单独提升为控件类
 * 2. 修复系统托盘多次创建内存增加问题
 * 3. 软件界面还原后系统托盘自动隐藏
 * 4. 关闭系统托盘通知
 * 5. 使用static_cast<int>消除size_t转换为int时的警告
 */



AppManager::AppManager(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::AppManager)
{
    ui->setupUi(this);

    setWindowTitle(QApplication::applicationDisplayName() + u8"_V1.10  作者： 张钿");

    // 窗口置顶切换
    connect(ui->actionmenu, &QAction::triggered, this, [&](){
        HWND hwnd = reinterpret_cast<HWND>(winId()); // 获取窗口句柄

        if ( ui->actionmenu->isChecked()) {
            SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
        }
        else {
            SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
        }
    });

    // this->setWindowFlags(this->windowFlags() & ~Qt::WindowMaximizeButtonHint);

    if (!init()) {
        qDebug() << u8"初始化失败，原因为：\n" << mError;
    }

    // createTray();

    timer.setInterval(500);

    connect(&timer, &QTimer::timeout, this, &AppManager::monitoring);

    timer.start();

    setAcceptDrops(true);
    installEventFilter(this);

}

AppManager::~AppManager()
{
    delete ui;
}

bool AppManager::init()
{
    QString filePath = QApplication::applicationDirPath() + CONFIG_FILE_PATH;
    QFileInfo fi(filePath);

    QString dirPath = fi.path();
    QDir dir;

    if (!dir.exists(dirPath)) {
        dir.mkpath(dirPath);
    }

    if (!fi.exists()) {
        QFile file(filePath);
        if(file.open(QIODevice::WriteOnly)){
            file.close();
        }
    }

#ifdef DEBUG_MODE
    reader.read(filePath);
#else
    reader.read(filePath);
#endif

    // 如果不存在数据库文件，创建新数据库文件
    if(!QFile::exists(DBFILE)) {
        createDatabase(DBFILE);
    } else {
        // 1. 连接 SQLite 数据库文件
        db = QSqlDatabase::addDatabase("QSQLITE");
        db.setDatabaseName(DBFILE);
    }


    // 创建标签控件
    pTab = new QTabWidget(this->centralWidget());
    if (!pTab) {
        addToError(QString::number(__LINE__));
        return false;
    };

    pTab->setMovable(true);


    pInputLineEdit = new QLineEdit(this);
    pInputLineEdit->hide();

    connect(pTab, &QTabWidget::tabBarDoubleClicked, this, [=](int index){
        QString oriText = pTab->tabText(index);
        pInputLineEdit->setFocus();
        pInputLineEdit->setText(oriText);
        pInputLineEdit->setFixedSize(pTab->tabBar()->tabRect(index).width(),
                               pTab->tabBar()->tabRect(index).height());
        pInputLineEdit->move(pTab->x() + pTab->tabBar()->tabRect(index).x(), ui->centralwidget->y() + pTab->y());
        pInputLineEdit->show();
        // 获取并遍历从配置文件读取的标签页对象
    });

    connect(pTab, &QTabWidget::tabBarClicked, this, [=](int index){
        if(!pInputLineEdit->isHidden()) {
            if(index != pTab->currentIndex())
                pInputLineEdit->hide();
        }
    });

    // 获取并遍历从配置文件读取的标签页对象
    QList<TAB>* p = reader.getTabList();

    connect(pInputLineEdit, &QLineEdit::editingFinished, this, [=](){
        // 判断标签页是否有同名标签，如果有则取消修改
        for(int i = 0; i < pTab->count(); ++i) {
            if(pTab->tabText(i) == pInputLineEdit->text()) {
                pInputLineEdit->hide();
                return;
            }
        }
        if(!pInputLineEdit->text().isEmpty()){
            pTab->tabBar()->setTabText(pTab->currentIndex(), pInputLineEdit->text());
            (*p)[pTab->currentIndex()].name = pInputLineEdit->text();
            reader.write();
        }
        pInputLineEdit->hide();
    });


    // 获取 tabBar 并连接 tabMoved 信号
    QTabBar *tabBar = pTab->tabBar();
    connect(tabBar, &QTabBar::tabMoved, [&](int from, int to) {
        reader.getTabList()->swapItemsAt(from, to);
        reader.write();
    });


    connect(pInputLineEdit, &QLineEdit::inputRejected, this, [=](){
        pInputLineEdit->hide();
    });

    connect(pInputLineEdit, &QLineEdit::returnPressed, pTab, [=](){
        // 判断标签页是否有同名标签，如果有则取消修改
        for(int i = 0; i < pTab->count(); ++i) {
            if(pTab->tabText(i) == pInputLineEdit->text()) {
                pInputLineEdit->hide();
                return;
            }
        }
        if(!pInputLineEdit->text().isEmpty()){
            pTab->tabBar()->setTabText(pTab->currentIndex(), pInputLineEdit->text());
            (*p)[pTab->currentIndex()].name = pInputLineEdit->text();
            reader.write();
        }
        pInputLineEdit->hide();
    });

    // 创建纵向布局并添加至主窗口的centralWidget中央控件中
    QVBoxLayout* layout = new QVBoxLayout;
    if (!layout) {
        addToError(QString::number(__LINE__));
        return false;
    };

    this->centralWidget()->setLayout(layout);

    // 布局中添加标签控件
    layout->addWidget(pTab);

    // 创建按钮区域，并添加至centralWidget的布局layout中
    buttonArea = new QWidget;
    if (!buttonArea) {
        addToError(QString::number(__LINE__));
        return false;
    };

    layout->addWidget(buttonArea);


    // 给按钮区域添加横向布局
    QHBoxLayout* buttonAreaLayout = new QHBoxLayout;
    if (!buttonAreaLayout) {
        addToError(QString::number(__LINE__));
        return false;
    };

    buttonArea->setLayout(buttonAreaLayout);

    // 创建一键打开按钮
    startAllButton = new QPushButton(u8"一键打开");
    if (!startAllButton) {
        addToError(QString::number(__LINE__));
        return false;
    };
    // connect(startAllButton, SIGNAL(clicked()), this, SLOT(startAll()));
    connect(startAllButton, &QPushButton::clicked, this, [&](){
        startAll(0);
    });

    // 创建一键关闭按钮
    killAllButton = new QPushButton(u8"一键关闭");
    if (!killAllButton) {
        addToError(QString::number(__LINE__));
        return false;
    };
    // connect(killAllButton, SIGNAL(clicked()), this, SLOT(killAll()));
    connect(killAllButton, &QPushButton::clicked, this, [&](){
        killAll(0);
    });


    // 创建添加标签页按钮
    QPushButton* addTabButton = new QPushButton(u8"添加标签页");
    QPushButton* delTabButton = new QPushButton(u8"删除当前标签页");

    if (!addTabButton) {
        addToError(QString::number(__LINE__));
        return false;
    };

    connect(addTabButton, &QPushButton::clicked, this, [=](){
        // 新建标签页，并将控件添加至标签控件
        QString name = u8"新建标签页" + QString::number(pTab->count());
        // 判断标签页是否有同名标签，如果有则取消修改
        for(int i = 0; i < pTab->count(); ++i) {
            if(pTab->tabText(i) == name) name += QString::fromUtf8(u8"副本");
        }

        addNewTab(name);
        TAB tab = {name};
        p->push_back(tab);
        reader.write();
        delTabButton->setEnabled(true);

    });

    // 创建添加标签页按钮
    if (!delTabButton) {
        addToError(QString::number(__LINE__));
        return false;
    };
    connect(delTabButton, &QPushButton::clicked, this, [=](){

        // 弹出确认对话框
        int ret = QMessageBox::question(nullptr, u8"确认", u8"您确定要删除吗？", QMessageBox::Yes | QMessageBox::No);

        if (ret == QMessageBox::No) {
            return;
        }
        QWidget* page = pTab->currentWidget();
        killPage(0, page);

        // 新建标签页，并将控件添加至标签控件
        if(pTab->tabBar()->count() < 0) {
            delTabButton->setDisabled(true);
            return;
        }
        deleteTab(pTab->currentIndex());

    });


    // 将一键打开和一键关闭按钮添加的按钮区域的布局中，并添加弹簧空间等控制按钮间隔
    buttonAreaLayout->addStretch();
    buttonAreaLayout->addWidget(addTabButton);
    buttonAreaLayout->addWidget(delTabButton);
    buttonAreaLayout->addStretch();
    buttonAreaLayout->addWidget(startAllButton);
    buttonAreaLayout->addWidget(killAllButton);
    buttonAreaLayout->addStretch();

    if (p) {
        if(p->length() <= 0) {
            QString name = u8"新建标签页" + QString::number(pTab->count());
            addNewTab(name);
            TAB tab = {name};
            p->push_back(tab);
            reader.write();
            return true;
        }
        for(int tmpIndex = 0; tmpIndex < p->length(); ++tmpIndex) {
            for(int i = 0; i < (*p)[tmpIndex].list.length(); ++i) {
                int count = 0;
                for(int j = 0; j < (*p)[tmpIndex].list.length(); ++j) {
                    if((*p)[tmpIndex].list[ i ].name == (*p)[tmpIndex].list[ j ].name) {
                        ++count;
                    }
                }
                if(count > 1) {
                    for(int n = (*p)[tmpIndex].list.length() - 1; n >= i; --n) {
                        if((*p)[tmpIndex].list[ n ].name == (*p)[tmpIndex].list[ i ].name) {
                            if(count != 1)
                                (*p)[tmpIndex].list[ n ].name += u8"_副本" + QString::number(--count);
                        }
                    }
                    reader.write();
                }
            }
        }

        for (QList<TAB>::iterator it = p->begin(); it != p->end(); ++it) {
            // 新建标签页，并将控件添加至标签控件
            QVBoxLayout* layout = addNewTab((*it).name);

            // 添加该标签内容，遍历每个标签页对象中的属性
            for (QList<CONFIGOBJECT>::iterator subIt = (*it).list.begin(); subIt != (*it).list.end(); ++subIt) {
                // 创建单行控件对象，并添加至标签页的纵向布局

                QWidget* line = createAppLine(subIt->name, subIt->path, true);
                if(line == nullptr) {
                    continue;
                }
                layout->insertWidget(layout->count() - 1, line);
            }

        }
    }


    return true;
}

// void AppManager::startPage()
// {
//     QString error;
//     QWidget* page = pTab->currentWidget();
//     // QList<QWidget *> lines = page->findChildren<QWidget *>();
//     QList<QLineEdit*> lineEdits = page->findChildren<QLineEdit *>();
//     HWND hwnd = reinterpret_cast<HWND>(winId()); // 获取窗口句柄

//     SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

//     // for(auto const& line : std::as_const(lines)) {
//     for(auto const& lineEdit : std::as_const(lineEdits)) {
//         // if (line->objectName() != "line") continue;
//         // QLineEdit* lineEdit = line->findChildren<QLineEdit *>()[0];
//         int index = mLEList.indexOf(lineEdit);
//         QString path = lineEdit->text().trimmed();
//         if (path.startsWith("\"") && path.endsWith("\"")) {
//             path = path.mid(1, path.length() - 2);
//         }
//         QFileInfo fi(path);

//         QString workDir = fi.absoluteDir().absolutePath();
//         if (!fi.exists()) {
//             error.append(lineEdit->text() + u8"路径错误或文件不存在\n");
//             continue;
//         }

//         QProcess* process = new QProcess;
//         process->setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) {
//             args->flags |= CREATE_NEW_CONSOLE;
//             args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
//         });

//         QString exeName;
//         if ("exe" == lineEdit->text().split("/").last().split(".").last().toLower()){
//             exeName = lineEdit->text().split("/").last();
//         }
//         if ("bat" == lineEdit->text().split("/").last().split(".").last().toLower()){
//             QFile file(lineEdit->text());
//             file.open(QFile::ReadOnly);
//             QTextStream in(&file);

//             while(!in.atEnd()){
//                 QString str = in.readLine();
//                 if(str.contains(".exe")) exeName = getExeName(str);
//             }

//             file.close();
//         }

//         mRunLBList.at(index)->setObjectName(exeName);

//         process->setWorkingDirectory(workDir);
//         process->start("cmd.exe", QStringList() << "/k" << fi.fileName());
//         process->waitForStarted();

//         QTimer* checkTimer = new QTimer;

//         connect(checkTimer, &QTimer::timeout, this, [=](){
//             if(index >= mProcessIdList.length() || index >= checkCountList.length()) return;
//             // qDebug()<<exeName;
//             mProcessIdList[index].pID1 = getProcessID(exeName);
//             mProcessIdList[index].pID2 = process->processId();
//             processMap[mProcessIdList[index].pID2] = process;
//             if(mProcessIdList[index].pID1 != 0 || checkCountList[index] > 20) {
//                 emit startFinished();
//                 checkCountList[index] = 0;
//             }
//             ++checkCountList[index];
//             // qDebug()<< mProcessIdList[index].pID1 << mProcessIdList[index].pID2;
//         });

//         connect(this, &AppManager::startFinished, checkTimer, &QTimer::deleteLater);
//         connect(this, &AppManager::startFinished, process, &QProcess::kill);

//         checkTimer->start(500);
//         QThread::sleep(1);

//     }
//     if ( !ui->actionmenu->isChecked() )  SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
//     if(!error.isEmpty()) QMessageBox::warning(this, u8"警告", error, QMessageBox::Ok);
// }

void AppManager::startPage(int subIndex, QWidget* page)
{
    QString error;
    // QWidget* page = pTab->currentWidget();
    // QList<QWidget *> lines = page->findChildren<QWidget *>();
    QList<QLineEdit*> lineEdits = page->findChildren<QLineEdit *>();
    if (subIndex >= lineEdits.length()) return;


    HWND hwnd = reinterpret_cast<HWND>(winId()); // 获取窗口句柄

    QLineEdit* lineEdit = lineEdits.at(subIndex);

    int index = mLEList.indexOf(lineEdit);

    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

    QString path = lineEdit->text().trimmed();
    if (path.startsWith("\"") && path.endsWith("\"")) {
        path = path.mid(1, path.length() - 2);
    }
    QFileInfo fi(path);

    QString workDir = fi.absoluteDir().absolutePath();
    if (!fi.exists()) {
        error.append(lineEdit->text() + u8"路径错误或文件不存在\n");
        return;
    }

    QProcess* process = new QProcess;
    process->setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) {
        args->flags |= CREATE_NEW_CONSOLE;
        args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
    });

    QString exeName;
    if ("exe" == lineEdit->text().split("/").last().split(".").last().toLower()){
        exeName = lineEdit->text().split("/").last();
    }
    if ("bat" == lineEdit->text().split("/").last().split(".").last().toLower()){
        QFile file(lineEdit->text());
        file.open(QFile::ReadOnly);
        QTextStream in(&file);

        while(!in.atEnd()){
            QString str = in.readLine();
            if(str.contains(".exe")) exeName = getExeName(str);
        }

        file.close();
    }

    mRunLBList.at(index)->setObjectName(exeName);

    process->setWorkingDirectory(workDir);
    process->start("cmd.exe", QStringList() << "/k" << fi.fileName());
    process->waitForStarted();

    QTimer* checkTimer = new QTimer;
    connect(checkTimer, &QTimer::timeout, this, [=](){
        if(index >= mProcessIdList.length() || index >= checkCountList.length()) return;
        mProcessIdList[index].pID1 = getProcessID(exeName);
        mProcessIdList[index].pID2 = process->processId();
        processMap[mProcessIdList[index].pID2] = process;
        if(mProcessIdList[index].pID1 != 0 || checkCountList[index] > 20) {
            emit startFinished();
            checkCountList[index] = 0;
            updateData(index, exeName, mProcessIdList[index].pID1, mProcessIdList[index].pID2);
            startPage(subIndex + 1, page);
        }
        ++checkCountList[index];
    });

    connect(this, &AppManager::startFinished, checkTimer, &QTimer::deleteLater);
    connect(this, &AppManager::startFinished, process, &QProcess::kill);

    checkTimer->start(500);

    if ( !ui->actionmenu->isChecked() )  SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    if(!error.isEmpty()) QMessageBox::warning(this, u8"警告", error, QMessageBox::Ok);
}

// void AppManager::killPage()
// {
//     QWidget* page = pTab->currentWidget();
//     QList<QWidget *> lines = page->findChildren<QWidget *>();

//     for(auto const& line : std::as_const(lines)) {
//         if (line->objectName() != "line") continue;
//         QLineEdit* lineEdit = line->findChildren<QLineEdit *>()[0];
//         int index = mLEList.indexOf(lineEdit);
//         if(mRunLBList.at(index)->text() == u8"程序已关闭") continue;
//         killProcess(mRunLBList.at(index)->objectName(), mProcessIdList.at(index).pID1);

//         if(processMap.isEmpty()) continue;
//         if(processMap[mProcessIdList.at(index).pID2] == nullptr) continue;
//         if(processMap[mProcessIdList.at(index).pID2]->state() == QProcess::Running) {
//             processMap[mProcessIdList.at(index).pID2]->kill();
//             processMap[mProcessIdList.at(index).pID2]->waitForFinished();
//         }
//         delete processMap[mProcessIdList.at(index).pID2];
//         processMap[mProcessIdList.at(index).pID2] = nullptr;
//         QThread::sleep(1);
//     }
// }

void AppManager::killPage(int subIndex, QWidget* page)
{

    QList<QWidget *> lines = page->findChildren<QWidget *>();

    do {
        if (subIndex >= lines.length()) break;
        QWidget* line = lines.at(subIndex);
        if (line->objectName() != "line") break;

        QLineEdit* lineEdit = line->findChildren<QLineEdit *>()[0];

        int index = mLEList.indexOf(lineEdit);

        if(mRunLBList.at(index)->text() == u8"程序已关闭") break;
        killProcess(mRunLBList.at(index)->objectName(), mProcessIdList.at(index).pID1);

        if(processMap.isEmpty()) break;
        if(processMap[mProcessIdList.at(index).pID2] == nullptr) break;
        if(processMap[mProcessIdList.at(index).pID2]->state() == QProcess::Running) {
            processMap[mProcessIdList.at(index).pID2]->kill();
            processMap[mProcessIdList.at(index).pID2]->waitForFinished();
            updateData(subIndex, "exeName", 0, 0);
        }
        delete processMap[mProcessIdList.at(index).pID2];
        processMap[mProcessIdList.at(index).pID2] = nullptr;
    } while(0);

    if (subIndex < lines.length()) killPage(subIndex + 1, page);
    return;
}



// void AppManager::startAll()
// {
    // QString error;
    // HWND hwnd = reinterpret_cast<HWND>(winId()); // 获取窗口句柄

    // SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

    // for (int i = 0; i < mPBList.length(); ++i) {
    //     if(mRunLBList.at(i)->text() == u8"程序运行中") continue;
    //     QString path = mLEList.at(i)->text().trimmed();
    //     if (path.startsWith("\"") && path.endsWith("\"")) {
    //         path = path.mid(1, path.length() - 2);
    //     }
    //     QFileInfo fi(path);
    //     // QFileInfo fi(mLEList.at(i)->text());

    //     QString workDir = fi.absoluteDir().absolutePath();
    //     if (!fi.exists()) {
    //         error.append(mLEList.at(i)->text() + u8"路径错误或文件不存在\n");
    //         continue;
    //     }


    //     QString exeName;
    //     if ("exe" == mLEList.at(i)->text().split("/").last().split(".").last().toLower()) {
    //         exeName = mLEList.at(i)->text().split("/").last();
    //     }
    //     if ("bat" == mLEList.at(i)->text().split("/").last().split(".").last().toLower()) {
    //         QFile file(mLEList.at(i)->text());
    //         file.open(QFile::ReadOnly);
    //         QTextStream in(&file);
    //         while(!in.atEnd()){
    //             QString str = in.readLine();
    //             if(str.contains(".exe")) exeName = getExeName(str);
    //         }
    //         file.close();
    //     }

    //     mRunLBList.at(i)->setObjectName(exeName);
    //     QProcess* process = new QProcess;
    //     process->setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) {
    //         args->flags |= CREATE_NEW_CONSOLE;
    //         args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
    //     });

    //     process->setWorkingDirectory(workDir);
    //     process->start("cmd.exe", QStringList() << "/k" << fi.fileName());
    //     process->waitForStarted();

    //     QTimer* checkTimer = new QTimer;

    //     connect(checkTimer, &QTimer::timeout, this, [=](){
    //         if(i >= mProcessIdList.length() || i >= checkCountList.length()) return;
    //         mProcessIdList[i].pID1 = getProcessID(mRunLBList.at(i)->objectName());
    //         mProcessIdList[i].pID2 = process->processId();
    //         // mProcessIdList[i].pID2 = getProcessID("cmd.exe");
    //         processMap[mProcessIdList[i].pID2] = process;
    //         if(mProcessIdList[i].pID1 != 0 || checkCountList[i] > 20) {
    //             emit startFinished();
    //             checkCountList[i] = 0;
    //         }
    //         ++checkCountList[i];
    //     });

    //     connect(this, &AppManager::startFinished, checkTimer, &QTimer::deleteLater);
    //     connect(this, &AppManager::startFinished, process, &QProcess::kill);

    //     checkTimer->start(500);
    //     QThread::sleep(1);
    // }
    // if ( !ui->actionmenu->isChecked() )  SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

    // if(!error.isEmpty())QMessageBox::warning(this, u8"警告", error, QMessageBox::Ok);
// }

void AppManager::startAll(int subIndex)
{
    if (subIndex >= mRunLBList.length()) return;
    if(mRunLBList.at(subIndex)->text() == u8"程序运行中") return;
    QString error;
    HWND hwnd = reinterpret_cast<HWND>(winId()); // 获取窗口句柄

    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

    QString path = mLEList.at(subIndex)->text().trimmed();
    if (path.startsWith("\"") && path.endsWith("\"")) {
        path = path.mid(1, path.length() - 2);
    }
    QFileInfo fi(path);
    // QFileInfo fi(mLEList.at(subIndex)->text());

    QString workDir = fi.absoluteDir().absolutePath();
    if (!fi.exists()) {
        error.append(mLEList.at(subIndex)->text() + u8"路径错误或文件不存在\n");
    }


    QString exeName;
    if ("exe" == mLEList.at(subIndex)->text().split("/").last().split(".").last().toLower()) {
        exeName = mLEList.at(subIndex)->text().split("/").last();
    }
    if ("bat" == mLEList.at(subIndex)->text().split("/").last().split(".").last().toLower()) {
        QFile file(mLEList.at(subIndex)->text());
        file.open(QFile::ReadOnly);
        QTextStream in(&file);
        while(!in.atEnd()){
            QString str = in.readLine();
            if(str.contains(".exe")) exeName = getExeName(str);
        }
        file.close();
    }

    mRunLBList.at(subIndex)->setObjectName(exeName);
    QProcess* process = new QProcess;
    process->setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) {
        args->flags |= CREATE_NEW_CONSOLE;
        args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
    });

    process->setWorkingDirectory(workDir);
    process->start("cmd.exe", QStringList() << "/k" << fi.fileName());
    process->waitForStarted();

    QTimer* checkTimer = new QTimer;

    connect(checkTimer, &QTimer::timeout, this, [=](){
        if(subIndex >= mProcessIdList.length() || subIndex >= checkCountList.length()) return;
        mProcessIdList[subIndex].pID1 = getProcessID(mRunLBList.at(subIndex)->objectName());
        mProcessIdList[subIndex].pID2 = process->processId();
        // mProcessIdList[i].pID2 = getProcessID("cmd.exe");
        processMap[mProcessIdList[subIndex].pID2] = process;
        if(mProcessIdList[subIndex].pID1 != 0 || checkCountList[subIndex] > 20) {
            emit startFinished();
            checkCountList[subIndex] = 0;
            updateData(subIndex, exeName, mProcessIdList[subIndex].pID1, mProcessIdList[subIndex].pID2);
            startAll(subIndex + 1);
        }
        ++checkCountList[subIndex];
    });

    connect(this, &AppManager::startFinished, checkTimer, &QTimer::deleteLater);
    connect(this, &AppManager::startFinished, process, &QProcess::kill);

    checkTimer->start(500);


    if ( !ui->actionmenu->isChecked() )  SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

    if(!error.isEmpty())QMessageBox::warning(this, u8"警告", error, QMessageBox::Ok);
}


// void AppManager::killAll()
// {
    // for (int i = 0; i < mPBList.count(); ++i) {
    //     if(mRunLBList.at(i)->text() == u8"程序已关闭") continue;
    //     killProcess("cmd.exe", mProcessIdList.at(i).pID2);
    //     killProcess(mRunLBList.at(i)->objectName(), mProcessIdList.at(i).pID1);

    //     if(processMap.isEmpty()) continue;
    //     if(processMap[mProcessIdList.at(i).pID2] == 0) continue;
    //     if(processMap[mProcessIdList.at(i).pID2]->state() == QProcess::Running) {
    //         processMap[mProcessIdList.at(i).pID2]->kill();
    //         processMap[mProcessIdList.at(i).pID2]->waitForFinished();
    //     }
    //     processMap[mProcessIdList.at(i).pID1] = 0;
    //     processMap[mProcessIdList.at(i).pID2] = 0;
    //     QThread::sleep(1);
    // }
// }

void AppManager::killAll(int subIndex)
{
    do {
        if (subIndex >= mPBList.length()) break;
        if(mRunLBList.at(subIndex)->text() == u8"程序已关闭") break;
        killProcess("cmd.exe", mProcessIdList.at(subIndex).pID2);
        killProcess(mRunLBList.at(subIndex)->objectName(), mProcessIdList.at(subIndex).pID1);

        if(processMap.isEmpty()) break;
        if(processMap[mProcessIdList.at(subIndex).pID2] == 0) break;
        if(processMap[mProcessIdList.at(subIndex).pID2]->state() == QProcess::Running) {
            processMap[mProcessIdList.at(subIndex).pID2]->kill();
            processMap[mProcessIdList.at(subIndex).pID2]->waitForFinished();
        }
        processMap[mProcessIdList.at(subIndex).pID1] = 0;
        processMap[mProcessIdList.at(subIndex).pID2] = 0;

    } while(0);

    updateData(subIndex, "exeName", 0, 0);
    if (subIndex < mPBList.length()) killAll(subIndex + 1);

    return;
}

void AppManager::killProcess(const QString &processName, const int &processId)
{
    HANDLE hToolHelp32Snapshot;
    hToolHelp32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { sizeof(PROCESSENTRY32), 0, 0, 0, 0, 0, 0, 0, 0, 0};
    BOOL isSuccess = Process32First(hToolHelp32Snapshot, &pe);
    while (isSuccess)
    {
        int len = WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, static_cast<int>(wcslen(pe.szExeFile)), NULL, 0, NULL, NULL);
        char *des = (char *)malloc(sizeof(char) * (len + 1));
        WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, static_cast<int>(wcslen(pe.szExeFile)), des, len, NULL, NULL);
        des[len] = '\0';
        // qDebug()<< "compare:"<<processName<<QString::fromLocal8Bit(des) << processId << pe.th32ProcessID;
        if (processName == QString::fromLocal8Bit(des) && processId == pe.th32ProcessID)
        {
            // QProcess::execute("taskkill /F /PID " + QString::number(processId));
            QStringList arguments;
            arguments << "/F" << "/PID" << QString::number(processId);
            QProcess process;
            process.start("taskkill", arguments);
            // 等待进程执行完毕
            process.waitForFinished();
            free(des);
            break;
        }
        free(des);
        isSuccess = Process32Next(hToolHelp32Snapshot, &pe);
    }
    CloseHandle(hToolHelp32Snapshot);
}

void AppManager::monitoring()
{
    for (int i = 0; i < mLBList.length(); ++i) {
        bool res = queryRunningStateByIndexFromDB(i);
        // bool res = checkProcessRunning(mRunLBList.at(i)->objectName(), mProcessIdList[i].pID1);
        changeStatus(i, res);
    }
}

void AppManager::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason)
    {
    case QSystemTrayIcon::Trigger:
        this->showNormal();
        break;
    case QSystemTrayIcon::DoubleClick:
        this->showNormal();
        // tray->hide();
        break;
    case QSystemTrayIcon::MiddleClick:
        break;
    default:
        break;
    }
}

QIcon AppManager::fileExtensionIcon(const QString &filePath) const
{
    QFileIconProvider iconProvider;
    QFileInfo fileInfo(filePath);
    QIcon icon = iconProvider.icon(fileInfo);
    return icon;
}


void AppManager::resizeEvent(QResizeEvent* event)
{
    Q_UNUSED(event)
//    QSize oldSize = event->oldSize();
//    QSize size = event->size();

//    if (0 >= oldSize.width() || 0 == size.width() || 0 >= oldSize.height() || 0 == size.height()) return;

//    float vProportion = (float)size.height() / (float)oldSize.height();

////    for (qsizetype i = 0; i < mLWList.count(); i++) {
////        int height = mLWList.at(i)->height();
////        mLWList.at(i)->setFixedHeight(height * vProportion);
    ////    }
}

void AppManager::changeStatus(int index, bool runState)
{
    if (runState) {
        mPBList.at(index)->setText(u8"点击关闭程序");
        mPBList.at(index)->setStyleSheet("background-color:red");

        mRunLBList.at(index)->setText(u8"程序运行中");
        QPalette pal = mRunLBList.at(index)->palette();
        pal.setColor(QPalette::WindowText, Qt::green);
        mRunLBList.at(index)->setPalette(pal);
        mSwPBList.at(index)->setEnabled(true);
        mDelBtnList.at(index)->setDisabled(true);
        return;
    }
    mPBList.at(index)->setText(u8"点击打开程序");
    mPBList.at(index)->setStyleSheet("background-color:green");

    mRunLBList.at(index)->setText(u8"程序已关闭");
    QPalette pal = mRunLBList.at(index)->palette();
    pal.setColor(QPalette::WindowText, Qt::red);
    mRunLBList.at(index)->setPalette(pal);
    mSwPBList.at(index)->setDisabled(true);
    mDelBtnList.at(index)->setEnabled(true);

}

void AppManager::closeEvent(QCloseEvent *event)
{
    HWND hwnd = reinterpret_cast<HWND>(winId()); // 获取窗口句柄
    SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
    // 弹出确认对话框
    QMessageBox msgBox;
    msgBox.setWindowTitle(u8"提示");
    msgBox.setInformativeText(u8"是否完全退出？");
    QPushButton* button1 = msgBox.addButton(u8"完全退出", QMessageBox::AcceptRole);
    QPushButton* button2 = msgBox.addButton(u8"系统托盘显示", QMessageBox::RejectRole);

    msgBox.setDefaultButton(button1);

    msgBox.exec();
    // 根据用户选择的按钮执行不同的操作
    if (msgBox.clickedButton() == button1) {
        event->accept();
    }
    if (msgBox.clickedButton() == button2) {
        createTray();
        hide(); // 隐藏窗口
        event->ignore();
        QString text = QApplication::applicationDisplayName() + u8"已隐藏到系统托盘";
        QString title = u8"通知";
        tray->showMessage(title, text, QSystemTrayIcon::Information, 1000); // 最后一个参数为提示时长，默认 10000，即 10s
    }

    delete button1;
    delete button2;
    button1 = nullptr;
    button2 = nullptr;
    if ( ui->actionmenu->isChecked() ) SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

}

void AppManager::hideEvent(QHideEvent *event)
{
    if(!tray) return;
    if (tray->isVisible())
    {
        // hide(); // 隐藏窗口
        event->ignore(); // 忽略事件
    }
}


bool AppManager::checkProcessRunning(const QString &processName, int &processId)
{
#ifdef Q_OS_WIN
    bool res = false;
    HANDLE hToolHelp32Snapshot;
    hToolHelp32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { sizeof(PROCESSENTRY32), 0, 0, 0, 0, 0, 0, 0, 0, 0};
    BOOL isSuccess = Process32First(hToolHelp32Snapshot, &pe);
    // qDebug()<<"check status:" <<processName<<processId;
    while (isSuccess)
    {
        int len = WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, static_cast<int>(wcslen(pe.szExeFile)), NULL, 0, NULL, NULL);
        char *des = (char *)malloc(sizeof(char) * (len + 1));
        WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, static_cast<int>(wcslen(pe.szExeFile)), des, len, NULL, NULL);
        des[len] = '\0';
        // qDebug()<< processName << QString::fromLocal8Bit(des);
        if (processName == QString::fromLocal8Bit(des))
        {
            // qDebug()<< processName << processId << QString::fromWCharArray(pe.szExeFile);
            if (processId == pe.th32ProcessID) {
                res = true;
                free(des);
                break;
            }
        }
        free(des);
        isSuccess = Process32Next(hToolHelp32Snapshot, &pe);
    }
    CloseHandle(hToolHelp32Snapshot);
    return res;
#elif defined Q_OS_MAC
    bool res(false);
    QString strCommand = "ps -ef|grep " + processName + " |grep -v grep |awk '{print $2}'";

    const char* strFind_ComName = convertQString2char(strCommand);
    FILE * pPipe = popen(strFind_ComName, "r");
    if (pPipe)
    {
        std::string com;
        char name[512] = { 0 };
        while (fgets(name, sizeof(name), pPipe) != NULL)
        {
            int nLen = strlen(name);
            if (nLen > 0
                && name[nLen - 1] == '\n')
                //&& name[0] == '/')
            {
                name[nLen - 1] = '\0';
                listProcessId.append(atoi(name));
                res = true;
                break;
            }
        }
        pclose(pPipe);
    }
    return res;
#endif
}

QString AppManager::getExeName(QString str)
{
    QString res;
    QRegularExpression regex(R"(([^\\]+\.exe))");
    QRegularExpressionMatch match = regex.match(str);
    res = match.captured(0);

    return res;
}

int AppManager::getProcessID(QString exename)
{
    int res = 0;
    HANDLE hToolHelp32Snapshot;
    hToolHelp32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32 pe = { sizeof(PROCESSENTRY32), 0, 0, 0, 0, 0, 0, 0, 0, 0};
    BOOL isSuccess = Process32First(hToolHelp32Snapshot, &pe);

    while (isSuccess)
    {
        int len = WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, static_cast<int>(wcslen(pe.szExeFile)), NULL, 0, NULL, NULL);
        char *des = (char *)malloc(sizeof(char) * (len + 1));
        WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, static_cast<int>(wcslen(pe.szExeFile)), des, len, NULL, NULL);
        des[len] = '\0';
        // qDebug()<< "name check:" << exename << QString::fromLocal8Bit(des);
        if (exename == QString::fromLocal8Bit(des))
        {
            int count = 0;
            for(auto const & each : std::as_const(mProcessIdList)){
                if(each.pID1 == pe.th32ProcessID) {
                    ++count;
                    break;
                }
            }
            if(count == 0) res = pe.th32ProcessID;
        }
        free(des);
        isSuccess = Process32Next(hToolHelp32Snapshot, &pe);
    }
    CloseHandle(hToolHelp32Snapshot);

    return res;
}

void AppManager::switchApplication(DWORD pid) {
    EnumWindows(EnumWindowsProc, (LPARAM)pid);
}

void AppManager::createTray()
{
    // ***托盘***
    if(!tray) tray = new QSystemTrayIcon(this); // 初始化托盘对象 tray
    tray->setIcon(QIcon("://images/icon.ico")); // 设定托盘图标，引号内是自定义的 png 图片路径
    tray->setToolTip(QApplication::applicationDisplayName()); // 提示文字
    tray->show(); // 让托盘图标显示在系统托盘上
    // QString title = u8"通知";
    // QString text = QApplication::applicationDisplayName() + u8"已启动系统托盘";
    // tray->showMessage(title, text, QSystemTrayIcon::Information, 500); // 最后一个参数为提示时长，默认 10000，即 10s

    // 创建菜单项动作
    // minimizeAction = new QAction("minwin", this);
    // connect(minimizeAction, &QAction::triggered, this, &AppManager::hide);
    if(!restoreAction) restoreAction = new QAction(u8"还原", this);
    connect(restoreAction, &QAction::triggered, this, &AppManager::showNormal);
    connect(restoreAction, &QAction::triggered, tray, &QSystemTrayIcon::hide);
    if(!quitAction) quitAction = new QAction(u8"退出", this);
    connect(quitAction, &QAction::triggered, qApp, &QApplication::quit); // 关闭应用

    // 创建托盘菜单
    if(!trayMenu) trayMenu = new QMenu(this);
    // trayMenu->addAction(minimizeAction);
    trayMenu->addAction(restoreAction);
    trayMenu->addSeparator();
    trayMenu->addAction(quitAction);
    tray->setContextMenu(trayMenu);
    connect(tray, &QSystemTrayIcon::activated, this, &AppManager::iconActivated);
}

// QLabel *AppManager::createLabel(QString name, int width)
// {
//     QLabel* label = new QLabel;
//     if (!label) {
//         mError += "appmanager.cpp line 105, pointer \"label\" is NULL\n";
//         return nullptr;
//     };

//     label->setText(name);
//     QFont font = label->font();
//     font.setBold(true);
//     label->setFont(font);
//     label->setObjectName("AppName");
//     // label->setAccessibleName(name + QString::number(++nameCount));
//     // qDebug()<<fi.fileName()<<fi.fileName().split(".")[0];
//     // label->setAccessibleName(fi.fileName().split(".")[0]);
//     mLBList.append(label);

//     label->setFixedWidth(width);

//     return label;
// }

// QLabel *AppManager::createIcon(QString filePath, int width)
// {
//     QLabel* icon = new QLabel;
//     if (!icon) {
//         return nullptr;
//     };

//     icon->setObjectName("icon");
//     QIcon appIcon = fileExtensionIcon(filePath);
//     // pixmap.scaled(width, width, Qt::KeepAspectRatio, Qt::SmoothTransformation);
//     icon->setFixedSize(width + 10, width + 10);
//     icon->setPixmap(appIcon.pixmap(width, width));
//     icon->setAlignment(Qt::AlignCenter);
//     return icon;
// }

// QLineEdit *AppManager::createLineEdit(QString text)
// {
//     QLineEdit* lineEdit = new QLineEdit;
//     if (!lineEdit) {
//         addToError(QString::number(__LINE__));
//         return nullptr;
//     };

//     lineEdit->setText(text);
//     mLEList.append(lineEdit);
//     lineEdit->setObjectName("pathLineEdit");
//     lineEdit->setAcceptDrops(true);
//     lineEdit->installEventFilter(this);

//     connect(lineEdit, &QLineEdit::textChanged, this, [=](){
//         QUrl url(lineEdit->text());
//         // 使用 QUrl::isValid() 检查 URL 是否有效
//         // 使用 QUrl::scheme() 检查 URL 的协议是否存在
//         QString path;
//         if(url.isValid() && !url.scheme().isEmpty())
//             path = url.toLocalFile();
//         if(path.isEmpty()) return;
//         QString filePath = path;
//         QFileInfo fi(path);
//         if(fi.fileName().split(".").last() == "lnk") {
//             filePath = GetLinkTarget(path);
//         }
//         if (filePath.startsWith("\"") && filePath.endsWith("\"")) {
//             filePath = filePath.mid(1, filePath.length() - 2);
//         }
//         lineEdit->setText(convertWindowsToLinuxPath(filePath));
//     });
//     return lineEdit;
// }

// QLabel *AppManager::createStatus()
// {
//     QLabel* state = new QLabel;
//     state->setText(u8"程序已关闭");
//     QPalette pal = state->palette();
//     pal.setColor(QPalette::WindowText, Qt::red);
//     state->setPalette(pal);
//     mRunLBList.append(state);
//     state->setObjectName("state");
//     return state;
// }

// QToolButton *AppManager::createToolButton()
// {
//     QToolButton* toolButton = new QToolButton;
//     if (!toolButton) {
//         mError += "appmanager.cpp line 93, pointer \"toolButton\" is NULL\n";
//         return nullptr;
//     };
//     toolButton->setText("...");
//     return toolButton;
// }

// QPushButton *AppManager::createSwitchButton()
// {
//     QPushButton* switchButton = new QPushButton(u8"切换窗口");
//     if (!switchButton) {
//         addToError(QString::number(__LINE__));
//         return nullptr;
//     };
//     mSwPBList.append(switchButton);
//     switchButton->setDisabled(true);
//     return switchButton;
// }

void AppManager::addToError(QString line)
{
    mError += "line " + line +  " in " + QString(__FILE__) + "\n";
}

QVBoxLayout* AppManager::addNewTab(QString tabName)
{
    // 新建标签页，并将控件添加至标签控件
    QWidget* page = new QWidget;
    page->setObjectName("page");


    if (!page) {
        addToError(QString::number(__LINE__));
        return nullptr;
    };

    pTab->addTab(page, tabName);

    QVBoxLayout* vLayout = new QVBoxLayout;
    // 给标签页纵向布局
    if (!vLayout) {
        addToError(QString::number(__LINE__));
        return nullptr;
    };

    page->setLayout(vLayout);

    QScrollArea* scrollArea = new QScrollArea;
    scrollArea->setWidgetResizable(true);
    QWidget* scrollWidget = new QWidget;
    QVBoxLayout* scrollLayout = new QVBoxLayout;
    scrollLayout->setAlignment(Qt::AlignCenter);
    if(!scrollArea) qDebug() << "scrollArea empty";
    vLayout->addWidget(scrollArea);
    scrollWidget->setLayout(scrollLayout);
    scrollArea->setWidget(scrollWidget);
    scrollLayout->setObjectName("srollLayout");
    scrollWidget->setObjectName("scrollWidget");


    QPushButton* addAppLine = new QPushButton(u8"新增App");

    if (!addAppLine) {
        delete addAppLine;
        addAppLine = nullptr;
        return nullptr;
    };

    connect(addAppLine, &QPushButton::clicked, this, [=](){

        bool ok;
        QString text = QInputDialog::getText(nullptr, u8"名称输入对话框", u8"请输入您的应用名称:", QLineEdit::Normal, "", &ok);

        if (!ok || text.isEmpty()) {
            // 在这里处理用户输入的字符串
            return;
        }

        QString newAppName;
        if(text.isEmpty()) newAppName = u8"新建App";
        else newAppName = text;

        QWidget* widget = createAppLine(newAppName);
        if(!widget) return;

        scrollLayout->insertWidget(scrollLayout->count() - 1, widget);
        if(widget->height() * scrollLayout->count() > scrollWidget->height()) {
            scrollWidget->setMaximumHeight(widget->height() * scrollLayout->count());
        }

        QList<TAB>* p = reader.getTabList();
        CONFIGOBJECT tmpObj;
        tmpObj.name = newAppName;
        tmpObj.path = "";
        (*p)[pTab->currentIndex()].list.push_back(tmpObj);

        reader.write();
    });


    // 添加打开本页程序
    // 创建一键打开按钮
    QPushButton* startPageButton = new QPushButton(u8"打开本页所有程序");
    if (!startPageButton) {
        delete startPageButton;
        startPageButton = nullptr;
        return nullptr;
    };

    // connect(startPageButton, SIGNAL(clicked()), this, SLOT(startPage()));
    connect(startPageButton, &QPushButton::clicked, this, [&](){
        QWidget* page = pTab->currentWidget();
        startPage(0, page);
    });

    // 创建一键关闭按钮
    QPushButton* killPageButton = new QPushButton(u8"关闭本页所有程序");
    if (!killPageButton) {
        delete killPageButton;
        killPageButton = nullptr;
        return nullptr;
    };
    // connect(killPageButton, SIGNAL(clicked()), this, SLOG(killPage()));
    connect(killPageButton, &QPushButton::clicked, this, [&](){
        QWidget* page = pTab->currentWidget();
        killPage(0, page);
    });

    // 将一键打开和一键关闭按钮添加的按钮区域的布局中，并添加弹簧空间等控制按钮间隔
    QWidget* pageButtonArea = new QWidget;

    scrollLayout->addWidget(pageButtonArea);

    // pageButtonArea->setFixedHeight(40);

    QHBoxLayout* pageButtonAreaLayout = new QHBoxLayout(pageButtonArea);
    pageButtonAreaLayout->addStretch();
    pageButtonAreaLayout->addWidget(addAppLine);
    pageButtonAreaLayout->addStretch();
    pageButtonAreaLayout->addWidget(startPageButton);
    pageButtonAreaLayout->addWidget(killPageButton);
    pageButtonAreaLayout->addStretch();

    return scrollLayout;

}

void AppManager::deleteTab(int index)
{
    QWidget* page = pTab->widget(index);
    QList<TAB>* p = reader.getTabList();
    p->removeAt(index);
    reader.write();


    QList<QLabel *> labels = page->findChildren<QLabel *>();
    for(auto const &label : std::as_const(labels)){
        if(label->objectName() == "AppName") {
            int subIndex = mLBList.indexOf(label);
            if (subIndex >= 0) {
                mLBList.removeAt(subIndex);
                mPBList.removeAt(subIndex);
                mRunLBList.removeAt(subIndex);
                mSwPBList.removeAt(subIndex);
                mDelBtnList.removeAt(subIndex);
                checkCountList.removeLast();
            }
        }
    }


    pTab->removeTab(index);

}

QWidget* AppManager::createAppLine(QString& name, QString lineEditText, bool flag)
{

    AppLine* line = new AppLine;

    if (!line) {
        addToError(QString::number(__LINE__));
        return nullptr;
    };

    line->setObjectName("line");
    line->installEventFilter(this);

    line->setFixedHeight(60);

    // 检查名称
    if(!flag) name = getNewName(name);

    QLabel* label = line->getAppNameLabel();

    label->setText(name);
    QFont font = label->font();
    font.setBold(true);
    label->setFont(font);
    label->setObjectName("AppName");
    // label->setAccessibleName(name + QString::number(++nameCount));
    // qDebug()<<fi.fileName()<<fi.fileName().split(".")[0];
    // label->setAccessibleName(fi.fileName().split(".")[0]);
    mLBList.append(label);
    label->setFixedWidth(line->width() / 4);


    QLabel* icon = line->getIconLabel();

    if (!icon) {
        return nullptr;
    };

    icon->setObjectName("icon");
    QIcon appIcon = fileExtensionIcon(lineEditText);
    // pixmap.scaled(width, width, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    int width = line->height() / 2;
    icon->setFixedSize(width + 10, width + 10);
    icon->setPixmap(appIcon.pixmap(width, width));
    icon->setAlignment(Qt::AlignCenter);

    QLineEdit* lineEdit = line->getLineEdit();

    if (!lineEdit) {
        addToError(QString::number(__LINE__));
        return nullptr;
    };

    lineEdit->setText(lineEditText);
    mLEList.append(lineEdit);
    lineEdit->setObjectName("pathLineEdit");
    lineEdit->setAcceptDrops(true);
    lineEdit->installEventFilter(this);

    connect(lineEdit, &QLineEdit::textChanged, this, [=](){
        QUrl url(lineEdit->text());
        // 使用 QUrl::isValid() 检查 URL 是否有效
        // 使用 QUrl::scheme() 检查 URL 的协议是否存在
        QString path;
        if(url.isValid() && !url.scheme().isEmpty())
            path = url.toLocalFile();
        if(path.isEmpty()) return;
        QString filePath = path;
        QFileInfo fi(path);
        if(fi.fileName().split(".").last() == "lnk") {
            filePath = GetLinkTarget(path);
        }
        if (filePath.startsWith("\"") && filePath.endsWith("\"")) {
            filePath = filePath.mid(1, filePath.length() - 2);
        }
        lineEdit->setText(convertWindowsToLinuxPath(filePath));
    });

    QLabel* runningState = line->getRunningStatusLabel();
    runningState->setText(u8"程序已关闭");
    QPalette pal = runningState->palette();
    pal.setColor(QPalette::WindowText, Qt::red);
    runningState->setPalette(pal);
    mRunLBList.append(runningState);
    runningState->setObjectName("state");


    QToolButton* toolButton = line->getToolButton();
    connect(toolButton, &QToolButton::clicked, this, [=](){
        QFileDialog dlg;
        QString defaultPath = "c:/";
        if (!lineEdit->text().isEmpty()) {
            QFileInfo fileInfo(lineEdit->text());
            defaultPath = fileInfo.absolutePath();
        }

        QString path = QString::fromUtf8(dlg.getOpenFileName(this, u8"选择文件", defaultPath, u8"选择启动程序(*.exe *.bat)").toUtf8());

        if (0 < path.length()) {
            lineEdit->clear();
            lineEdit->setText(path);
            // To Do 此处添加修改配置文件的代码
            QList<TAB>* p = reader.getTabList();
            for(auto &app : (*p)[pTab->currentIndex()].list){
                if(app.name == name){
                    app.path = path;
                    break;
                }
            }
            reader.write();
            QIcon appIcon = fileExtensionIcon(path);
            icon->setPixmap(appIcon.pixmap(icon->width() - 10, icon->width() - 10));
            icon->setAlignment(Qt::AlignCenter);
        }

    });

    QPushButton* switchButton = line->getSwitchButton();
    switchButton->setText(u8"切换窗口");

    if (!switchButton) {
        addToError(QString::number(__LINE__));
        return nullptr;
    };
    mSwPBList.append(switchButton);
    switchButton->setDisabled(true);

    connect(switchButton, &QPushButton::clicked, this, [=](){
        int index = mLBList.indexOf(label);
        // QString path = lineEdit->text();
        switchApplication(mProcessIdList[index].pID1);
        // if("exe" == path.split(".").last().toLower())
        // if("bat" == path.split(".").last().toLower()) {
        //     switchApplication(mProcessIdList[index].pID2);
        // }
    });

    // 创建开关按钮
    QPushButton* button = line->getStartButton();
    button->setText(u8"点击打开程序");
    if (!button) {
        addToError(QString::number(__LINE__));
        return nullptr;
    };
    // QPalette pal = button->palette();
    pal.setColor(QPalette::ButtonText, Qt::white);
    button->setStyleSheet("background-color:green");
    button->setPalette(pal);


    PROCESS_ID_PAIR pair;
    pair.pID1 = 0;
    pair.pID2 = 0;
    mProcessIdList.append(pair);

    int index = mLBList.indexOf(label);
    if(!isAppInDB(index)) {
        insertData(index, "AppName", 0, 0);
    }
    else {
        QString appName =queryAppNameByIndexFromDB(index);
        button->setObjectName(appName);
        runningState->setObjectName(appName);
        mProcessIdList[index].pID1 = queryPID1ByIndexFromDB(index);
        mProcessIdList[index].pID2 = queryPID2ByIndexFromDB(index);
    }

    quint8 checkCount = 0;
    checkCountList.append(checkCount);

    connect(button, &QPushButton::clicked, this, [=](){
        QString path = lineEdit->text().trimmed();
        if (path.startsWith("\"") && path.endsWith("\"")) {
            path = path.mid(1, path.length() - 2);
        }
        QFileInfo fi(path);
        if (!fi.exists()) {
            QMessageBox::warning(NULL, u8"警告", path + u8"文件路径错误或不存在,请检查！", QMessageBox::Ok);
            return;
        }

        if (u8"点击打开程序" == button->text()) {
            QStringList list = path.split("/");
            // QFileInfo fi(path);


            QString exeName;
            if ("exe" == list.last().split(".").last().toLower()){
                exeName = list.last();
            }
            if ("bat" == list.last().split(".").last().toLower()){
                QFile file(path);
                file.open(QFile::ReadOnly);
                QTextStream in(&file);
                while(!in.atEnd()){
                    QString str = in.readLine();
                    if(str.contains(".exe"))  {
                        exeName = getExeName(str);
                        break;
                    }
                }
                file.close();
            }

            QProcess* process = new QProcess;
            process->setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) {
                args->flags |= CREATE_NEW_CONSOLE;
                args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
            });

            button->setObjectName(exeName);
            runningState->setObjectName(exeName);


            process->setWorkingDirectory(fi.absoluteDir().absolutePath());
            process->start("cmd.exe", QStringList() << "/k" << fi.fileName());


            process->waitForStarted();

            QTimer* checkTimer = new QTimer;

            int index = mLBList.indexOf(label);
            connect(checkTimer, &QTimer::timeout, this, [=](){
                mProcessIdList[index].pID1 = getProcessID(mRunLBList[index]->objectName());
                mProcessIdList[index].pID2 = process->processId();
                processMap[mProcessIdList[index].pID2] = process;
                if(mProcessIdList[index].pID1 != 0 || checkCountList[index] > 20) {
                    emit startFinished();
                    checkCountList[index] = 0;
                    updateData(index, exeName, mProcessIdList[index].pID1, mProcessIdList[index].pID2);
                }
                ++checkCountList[index];
            });

            connect(this, &AppManager::startFinished, checkTimer, &QTimer::deleteLater);
            connect(this, &AppManager::startFinished, process, &QProcess::kill);

            checkTimer->start(500);


            return;
        }

        if (u8"点击关闭程序" == button->text()) {
            int index = mLBList.indexOf(label);
            killProcess(runningState->objectName(), mProcessIdList.at(index).pID1);
            if(processMap.isEmpty()) return;
            if(processMap[mProcessIdList.at(index).pID2] == nullptr) return;
            if (processMap[mProcessIdList.at(index).pID2]->state() == QProcess::Running) {
                processMap[mProcessIdList.at(index).pID2]->kill();
                processMap[mProcessIdList.at(index).pID2]->waitForFinished();
            }
            delete processMap[mProcessIdList.at(index).pID2];
            processMap[mProcessIdList.at(index).pID2] = nullptr;

            updateData(index, "exeName", 0, 0);
            return;
        }

    });

    mPBList.append(button);


    QPushButton* deCurLineButton = line->getDelButton();
    deCurLineButton->setText(u8"删除当前App");


    if (!deCurLineButton) {
        addToError(QString::number(__LINE__));
        return nullptr;
    };
    mDelBtnList.append(deCurLineButton);

    connect(deCurLineButton, &QPushButton::clicked, this, [=]{
        // 弹出确认对话框
        int ret = QMessageBox::question(nullptr, u8"确认", u8"您确定要删除吗？", QMessageBox::Yes | QMessageBox::No);

        if (ret == QMessageBox::No) {
            return;
        }

        int index = mLBList.indexOf(label);
        if(index < mLBList.length()) mLBList.removeAt(index);
        if(index < mPBList.length()) mPBList.removeAt(index);
        if(index < mLEList.length()) mLEList.removeAt(index);
        if(index < mRunLBList.length()) mRunLBList.removeAt(index);
        if(index < mSwPBList.length()) mSwPBList.removeAt(index);
        if(index < mDelBtnList.length()) mDelBtnList.removeAt(index);
        checkCountList.removeLast();


        QList<TAB>* p = reader.getTabList();
        int pos = 0;

        // 删除配置文件中对应内容
        for(auto &app : (*p)[pTab->currentIndex()].list){
            if(app.name == label->text()) {
                (*p)[pTab->currentIndex()].list.removeAt(pos);
                break;
            }
            ++pos;
        }
        reader.write();

        line->deleteLater();

    });


    // // 创建单行控件对象，并添加至标签页的纵向布局中
    // QWidget* line = new QWidget;
    // if (!line) {
    //     addToError(QString::number(__LINE__));
    //     return nullptr;
    // };

    // line->setObjectName("line");
    // line->installEventFilter(this);


    // // 给单行控件对象创建横向布局，并设置居中对齐
    // QHBoxLayout* lineLayout = new QHBoxLayout;
    // if (!lineLayout) {
    //     addToError(QString::number(__LINE__));
    //     delete line;
    //     return nullptr;
    // };

    // line->setLayout(lineLayout);
    // line->setFixedHeight(60);

    // // 检查名称
    // if(!flag) name = getNewName(name);

    // // 创建标签，用于显示属性名称
    // QLabel* label = createLabel(name, line->width() / 4);
    // if(!label) {
    //     delete line;
    //     return nullptr;
    // }

    // //创建Icon
    // QLabel* icon = createIcon(lineEditText, line->height() / 2);

    // // 创建可编辑行控件，用于显示属性值
    // QLineEdit* lineEdit = createLineEdit(lineEditText);

    // // 创建运行状态标签
    // QLabel* runningState = createStatus();

    // // 创建工具按钮，用于通过文件对话框修改lineEdit的属性值，并修改配置文件
    // QToolButton* toolButton = createToolButton();
    // connect(toolButton, &QToolButton::clicked, this, [=](){
    //     QFileDialog dlg;
    //     QString defaultPath = "c:/";
    //     if (!lineEdit->text().isEmpty()) {
    //         QFileInfo fileInfo(lineEdit->text());
    //         defaultPath = fileInfo.absolutePath();
    //     }

    //     QString path = QString::fromUtf8(dlg.getOpenFileName(this, u8"选择文件", defaultPath, u8"选择启动程序(*.exe *.bat)").toUtf8());

    //     if (0 < path.length()) {
    //         lineEdit->clear();
    //         lineEdit->setText(path);
    //         // To Do 此处添加修改配置文件的代码
    //         QList<TAB>* p = reader.getTabList();
    //         for(auto &app : (*p)[pTab->currentIndex()].list){
    //             if(app.name == name){
    //                 app.path = path;
    //                 break;
    //             }
    //         }
    //         reader.write();
    //         QIcon appIcon = fileExtensionIcon(path);
    //         icon->setPixmap(appIcon.pixmap(icon->width() - 10, icon->width() - 10));
    //         icon->setAlignment(Qt::AlignCenter);
    //     }

    // });


    // // 创建切换按钮
    // QPushButton* switchButton = createSwitchButton();
    // connect(switchButton, &QPushButton::clicked, this, [=](){
    //     int index = mLBList.indexOf(label);
    //     // QString path = lineEdit->text();
    //     switchApplication(mProcessIdList[index].pID1);
    //     // if("exe" == path.split(".").last().toLower())
    //     // if("bat" == path.split(".").last().toLower()) {
    //     //     switchApplication(mProcessIdList[index].pID2);
    //     // }
    // });



    // // 创建开关按钮
    // QPushButton* button = new QPushButton(u8"点击打开程序");
    // if (!button) {
    //     addToError(QString::number(__LINE__));
    //     return nullptr;
    // };
    // // QPalette pal = button->palette();
    // pal.setColor(QPalette::ButtonText, Qt::white);
    // button->setStyleSheet("background-color:green");
    // button->setPalette(pal);


    // PROCESS_ID_PAIR pair;
    // pair.pID1 = 0;
    // pair.pID2 = 0;
    // mProcessIdList.append(pair);

    // int index = mLBList.indexOf(label);
    // if(!isAppInDB(index)) {
    //     insertData(index, "AppName", 0, 0);
    // }
    // else {
    //     QString appName =queryAppNameByIndexFromDB(index);
    //     button->setObjectName(appName);
    //     runningState->setObjectName(appName);
    //     mProcessIdList[index].pID1 = queryPID1ByIndexFromDB(index);
    //     mProcessIdList[index].pID2 = queryPID2ByIndexFromDB(index);
    // }

    // quint8 checkCount = 0;
    // checkCountList.append(checkCount);

    // connect(button, &QPushButton::clicked, this, [=](){
    //     QString path = lineEdit->text().trimmed();
    //     if (path.startsWith("\"") && path.endsWith("\"")) {
    //         path = path.mid(1, path.length() - 2);
    //     }
    //     QFileInfo fi(path);
    //     if (!fi.exists()) {
    //         QMessageBox::warning(NULL, u8"警告", path + u8"文件路径错误或不存在,请检查！", QMessageBox::Ok);
    //         return;
    //     }

    //     if (u8"点击打开程序" == button->text()) {
    //         QStringList list = path.split("/");
    //         // QFileInfo fi(path);


    //         QString exeName;
    //         if ("exe" == list.last().split(".").last().toLower()){
    //             exeName = list.last();
    //         }
    //         if ("bat" == list.last().split(".").last().toLower()){
    //             QFile file(path);
    //             file.open(QFile::ReadOnly);
    //             QTextStream in(&file);
    //             while(!in.atEnd()){
    //                 QString str = in.readLine();
    //                 if(str.contains(".exe"))  {
    //                     exeName = getExeName(str);
    //                     break;
    //                 }
    //             }
    //             file.close();
    //         }

    //         QProcess* process = new QProcess;
    //         process->setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments *args) {
    //             args->flags |= CREATE_NEW_CONSOLE;
    //             args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES;
    //         });

    //         button->setObjectName(exeName);
    //         runningState->setObjectName(exeName);


    //         process->setWorkingDirectory(fi.absoluteDir().absolutePath());
    //         process->start("cmd.exe", QStringList() << "/k" << fi.fileName());


    //         process->waitForStarted();

    //         QTimer* checkTimer = new QTimer;

    //         int index = mLBList.indexOf(label);
    //         connect(checkTimer, &QTimer::timeout, this, [=](){
    //             mProcessIdList[index].pID1 = getProcessID(mRunLBList[index]->objectName());
    //             mProcessIdList[index].pID2 = process->processId();
    //             processMap[mProcessIdList[index].pID2] = process;
    //             if(mProcessIdList[index].pID1 != 0 || checkCountList[index] > 20) {
    //                 emit startFinished();
    //                 checkCountList[index] = 0;
    //                 updateData(index, exeName, mProcessIdList[index].pID1, mProcessIdList[index].pID2);
    //             }
    //             ++checkCountList[index];
    //         });

    //         connect(this, &AppManager::startFinished, checkTimer, &QTimer::deleteLater);
    //         connect(this, &AppManager::startFinished, process, &QProcess::kill);

    //         checkTimer->start(500);


    //         return;
    //     }

    //     if (u8"点击关闭程序" == button->text()) {
    //         int index = mLBList.indexOf(label);
    //         killProcess(runningState->objectName(), mProcessIdList.at(index).pID1);
    //         if(processMap.isEmpty()) return;
    //         if(processMap[mProcessIdList.at(index).pID2] == nullptr) return;
    //         if (processMap[mProcessIdList.at(index).pID2]->state() == QProcess::Running) {
    //             processMap[mProcessIdList.at(index).pID2]->kill();
    //             processMap[mProcessIdList.at(index).pID2]->waitForFinished();
    //         }
    //         delete processMap[mProcessIdList.at(index).pID2];
    //         processMap[mProcessIdList.at(index).pID2] = nullptr;

    //         updateData(index, "exeName", 0, 0);
    //         return;
    //     }

    // });

    // mPBList.append(button);


    // QPushButton* deCurLineButton = new QPushButton(u8"删除当前App");
    // if (!deCurLineButton) {
    //     addToError(QString::number(__LINE__));
    //     return nullptr;
    // };
    // mDelBtnList.append(deCurLineButton);

    // connect(deCurLineButton, &QPushButton::clicked, this, [=]{
    //     // 弹出确认对话框
    //     int ret = QMessageBox::question(nullptr, u8"确认", u8"您确定要删除吗？", QMessageBox::Yes | QMessageBox::No);

    //     if (ret == QMessageBox::No) {
    //         return;
    //     }

    //     int index = mLBList.indexOf(label);
    //     mLBList.removeAt(index);
    //     mPBList.removeAt(index);
    //     mLEList.removeAt(index);
    //     mRunLBList.removeAt(index);
    //     mSwPBList.removeAt(index);
    //     mDelBtnList.removeAt(index);
    //     checkCountList.removeLast();


    //     QList<TAB>* p = reader.getTabList();
    //     int pos = 0;

    //     for(auto &app : (*p)[pTab->currentIndex()].list){
    //         if(app.name == label->text()) {
    //             (*p)[pTab->currentIndex()].list.removeAt(pos);
    //         }
    //         ++pos;
    //     }
    //     reader.write();

    //     line->deleteLater();

    // });

    // 将标签，可编辑行，工具按钮，开关按钮添加至单行控件的横向布局中，并添加适当的弹簧控件和空白来控制间距
    if(!label) qDebug()<<"label empty";

    // lineLayout->addWidget(icon);
    // lineLayout->addWidget(label);
    // lineLayout->addWidget(lineEdit);
    // lineLayout->addWidget(toolButton);
    // lineLayout->addWidget(runningState);
    // lineLayout->addWidget(button);
    // lineLayout->addWidget(switchButton);
    // lineLayout->addWidget(deCurLineButton);

    return line;
}

bool AppManager::eventFilter(QObject *watched, QEvent *event)
{
    // qDebug()<<event->type();
    if (event->type() == QEvent::DragEnter) {
        QDragEnterEvent* dragEnterEvent = static_cast<QDragEnterEvent*>(event);
        if (dragEnterEvent->mimeData()->hasUrls())
            dragEnterEvent->acceptProposedAction();
    }
    if(watched == this) {
        if (event->type() == QEvent::Drop) {
            QDropEvent* dropEvent = static_cast<QDropEvent*>(event);
            if (dropEvent->mimeData()->hasUrls()) {
                QList<QUrl> list = dropEvent->mimeData()->urls();
                if(!list.first().isEmpty()) {
                    QList<QVBoxLayout*> layouts = pTab->currentWidget()->findChildren<QVBoxLayout*>();
                    QVBoxLayout* layout = nullptr;
                    for(auto const& obj : std::as_const(layouts)){
                        if(obj->objectName() == "srollLayout") {
                            layout = obj;
                        }
                    }
                    if(!layout) return false;
                    QString filePath = list.first().toLocalFile();
                    if(filePath.split(".").last() == "lnk") {
                        QString linkPath = filePath;
                        filePath = GetLinkTarget(linkPath);
                    }
                    filePath = convertWindowsToLinuxPath(filePath);
                    QFileInfo fi(filePath);
                    QStringList tmpList = fi.fileName().split(".");
                    tmpList.removeLast();
                    QString text = tmpList.join(".");
                    QWidget* line = createAppLine(text, filePath);
                    if(line == nullptr) {
                        return false;
                    }

                    layout->insertWidget(layout->count() - 1, line);
                    QList<QWidget*> widgets = pTab->currentWidget()->findChildren<QWidget*>();
                    for(auto const& widget : std::as_const(widgets)){
                        if(widget->objectName() == "srollWidget") {
                            if(line->height() * layout->count() > widget->height()) {
                                widget->setMaximumHeight(widget->height() * layout->count());
                            }
                        }
                    }

                    QList<TAB>* p = reader.getTabList();
                    CONFIGOBJECT tmpObj;
                    tmpObj.name = text;
                    tmpObj.path = filePath;
                    (*p)[pTab->currentIndex()].list.push_back(tmpObj);
                    reader.write();


                    dropEvent->acceptProposedAction();
                }
            }
        }
    }
    if(watched->objectName() == "pathLineEdit") {
        if (event->type() == QEvent::DragEnter) {
            QDragEnterEvent* dragEnterEvent = static_cast<QDragEnterEvent*>(event);
            if (dragEnterEvent->mimeData()->hasUrls()) {
                dragEnterEvent->acceptProposedAction();
            }
        }

        if (event->type() == QEvent::Drop) {
            QDropEvent* dropEvent = static_cast<QDropEvent*>(event);
            QLineEdit* lineEdit = static_cast<QLineEdit*>(watched);
            lineEdit->clear();
            if (dropEvent->mimeData()->hasUrls()) {
                QList<QUrl> list = dropEvent->mimeData()->urls();
                if(!list.first().isEmpty()) {
                    QString filePath = list.first().toLocalFile().trimmed();
                    if(filePath.split(".").last() == "lnk") {
                        QString linkPath = filePath;
                        filePath = GetLinkTarget(linkPath);
                    }
                    if (filePath.startsWith("\"") && filePath.endsWith("\"")) {
                        filePath = filePath.mid(1, filePath.length() - 2);
                    }
                    filePath = convertWindowsToLinuxPath(filePath);

                    // QFileInfo fi(filePath);
                    int width = 0;
                    QIcon appIcon = fileExtensionIcon(filePath);

                    int index = 0;
                    for(auto const& ob: mLEList) {
                        if(ob == watched) break;
                        ++index;
                    }

                    QList<QLineEdit*> lineEdits = pTab->currentWidget()->findChildren<QLineEdit*>();
                    index = 0;
                    for(auto const& ob: lineEdits) {
                        if(ob == watched) break;
                        ++index;
                    }

                    QList<QWidget*> widgets = pTab->currentWidget()->findChildren<QWidget*>();
                    int index2 = 0;
                    for(auto const& widget : std::as_const(widgets)) {
                        if(widget->objectName() == "line") {
                            if(index == index2) {
                                width = widget->height() / 2;
                                break;
                            }
                            ++index2;
                        }
                    }
                    // 保存配置
                    QList<TAB>* p = reader.getTabList();
                    // (*p)[pTab->currentIndex()].list[index].name = text;
                    (*p)[pTab->currentIndex()].list[index].path = filePath;
                    reader.write();

                    QList<QLabel*> labels = pTab->currentWidget()->findChildren<QLabel*>();
                    int index1 = 0;
                    for(auto &label : labels) {
                        // 修改图标
                        if(label->objectName() == "icon" ) {
                            if( index1 == index ) {
                                label->setPixmap(appIcon.pixmap(QSize(width, width)));
                                break;
                            }
                            ++index1;
                        }
                    }

                    dropEvent->acceptProposedAction();
                }
            }

        }
    }

    if(watched->objectName() == "line") {
        // 获取运行状态标签
        QList<QLabel*> labels = watched->findChildren<QLabel*>();
        for(auto const& lb : std::as_const(labels)) {
            if(lb->objectName() == "state") {
                if(lb->text() == u8"程序运行中")
                    return true;
            }
        }

        QList<QLineEdit*> lineEdits = watched->findChildren<QLineEdit*>();
        if(lineEdits.length() <= 0) return false;
        // QLineEdit* lineEdit = lineEdits[0];
        if (event->type() == QEvent::MouseButtonDblClick) {
            int index = getLineIndex(watched);
            QList<TAB>* p = reader.getTabList();
            bool ok;
            QString text = QInputDialog::getText(nullptr, u8"名称输入对话框", u8"请输入您的应用名称:", QLineEdit::Normal, (*p)[pTab->currentIndex()].list[index].name, &ok);

            if (!ok || text.isEmpty()) {
                // 在这里处理用户输入的字符串
                return false;
            }

            if(text == (*p)[pTab->currentIndex()].list[index].name) return true;

            text = getNewName(text);
            (*p)[pTab->currentIndex()].list[index].name = text;

            for(auto & label : labels) {
                if(label->objectName() == "AppName") {
                    label->setText(text);
                    break;
                }
            }

            mLBList.at(index)->setText(text);


            reader.write();
            this->update();
        }


        for(auto const& lb : std::as_const(labels)) {
            if(lb->objectName() == "state") {
                if(lb->text() == u8"程序运行中")
                    return QMainWindow::eventFilter(watched, event);
            }
        }
        // if (event->type() == QEvent::DragEnter) {
        //     QDragEnterEvent* dragEnterEvent = static_cast<QDragEnterEvent*>(event);
        //     if (dragEnterEvent->mimeData()->hasUrls())
        //         dragEnterEvent->acceptProposedAction();
        // }

        // if (event->type() == QEvent::Drop) {
        //     QDropEvent* dropEvent = static_cast<QDropEvent*>(event);
        //     if (dropEvent->mimeData()->hasUrls()) {
        //         QList<QUrl> list = dropEvent->mimeData()->urls();
        //         if(!list.first().isEmpty()) {
        //             QString filePath = list.first().toLocalFile();
        //             QFileInfo fi(filePath);
        //             int width = static_cast<QWidget*>(watched)->height() / 2;
        //             QIcon appIcon = fileExtensionIcon(filePath);

        //             int index = getLineIndex(watched);

        //             // QStringList tmpList = fi.fileName().split(".");
        //             // tmpList.removeLast();
        //             // QString text = tmpList.join(".");
        //             for(auto &label : labels) {
        //                 // // 修改标签名称
        //                 // if(label->objectName() == "AppName") {
        //                 //     label->setText(text);
        //                 // }
        //                 // 修改图标
        //                 if(label->objectName() == "icon") {
        //                     label->setPixmap(appIcon.pixmap(QSize(width, width)));
        //                 }
        //             }

        //             // 修改路径
        //             lineEdit->setText(filePath);

        //             // 保存配置
        //             QList<TAB>* p = reader.getTabList();
        //             // (*p)[pTab->currentIndex()].list[index].name = text;
        //             (*p)[pTab->currentIndex()].list[index].path = filePath;
        //             reader.write();
        //             dropEvent->acceptProposedAction();
        //         }
        //     }

        // }
    }


    return QMainWindow::eventFilter(watched, event);
}

int AppManager::getLineIndex(QObject *watched)
{
    QList<QWidget*> lines = pTab->widget(pTab->currentIndex())->findChildren<QWidget*>();
    int index = 0;
    for(auto const& tmp : std::as_const(lines)){
        if(tmp == watched) break;
        if(tmp->objectName() == "line")++index;
    }
    return index;
}

QString AppManager::getNewName(QString name)
{
    QList<TAB>* p = reader.getTabList();
    int count = 0;
    for(auto const&ob : (*p)[pTab->currentIndex()].list) {
        if(ob.name == name) {
            ++count;
            break;
        }
    }
    if (count == 0) return name;

    for(int index = 1; index <= (*p)[pTab->currentIndex()].list.length(); ++index) {
        count = 0;
        for(auto const&ob : (*p)[pTab->currentIndex()].list) {
            if(ob.name == name + u8"_副本" + QString::number(index)) {
                ++count;
                break;
            }
        }
        if (count == 0) return name + u8"_副本" + QString::number(index);
    }
    return "";
}


void AppManager::createDatabase(const QString &dbName)
{
    // 1. 连接 SQLite 数据库文件
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName(dbName);

    if (!db.open()) {
        qDebug() << "Error: Unable to open database!" << db.lastError().text();
        return;
    }

    // 2. 创建表
    QSqlQuery query;
    QString createTableSql = R"(
        CREATE TABLE IF NOT EXISTS apps (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            lb_index INTEGER NOT NULL,
            app_name TEXT NOT NULL,
            process_id1 INTEGER NOT NULL,
            process_id2 INTEGER NOT NULL
        )
    )";

    if (!query.exec(createTableSql)) {
        qDebug() << "Error: Failed to create table!" << query.lastError().text();
    } else {
        qDebug() << "Table created successfully!";
    }

    // 关闭数据库连接
    db.close();
}

void AppManager::insertData(const int index, const QString &appName, const int process_id1, const int process_id2)
{
    // 1. 连接到数据库
    if (!db.open()) {
        qDebug() << "Error: Unable to open database!" << db.lastError().text();
        return;
    }

    // 2. 插入数据
    QSqlQuery query;
    query.prepare("INSERT INTO apps (lb_index, app_name, process_id1, process_id2) VALUES (:index, :app, :pid1, :pid2)");
    query.bindValue(":index", index);
    query.bindValue(":app", appName);
    query.bindValue(":pid1", process_id1);
    query.bindValue(":pid2", process_id2);


    if (!query.exec()) {
        qDebug() << "Error: Failed to insert data!" << query.lastError().text();
    } else {
        qDebug() << "Data inserted successfully!";
    }

    // 关闭数据库连接
    db.close();
}

void AppManager::updateData(const int index, const QString &appName, const int process_id1, const int process_id2)
{
    // 连接到数据库
    if (!db.open()) {
        qDebug() << "Error: Unable to open database!" << db.lastError().text();
        return;
    }

    // 创建 SQL UPDATE 语句
    QSqlQuery query;
    query.prepare("UPDATE apps SET app_name = :app, process_id1 = :pid1, process_id2 = :pid2 WHERE lb_index = :index");
    query.bindValue(":app", appName);     // 更新应用名称
    query.bindValue(":pid1", process_id1);  // 更新进程ID1
    query.bindValue(":pid2", process_id2);  // 更新进程ID2
    query.bindValue(":index", index);     // 更新应用名称


    // 执行 SQL 语句
    if (!query.exec()) {
        qDebug() << "Error: Failed to update user!" << query.lastError().text();
    }

    // 提交更改并关闭数据库连接
    db.close();
}

bool AppManager::queryRunningStateByIndexFromDB(const int index)
{
    bool res = false;
    // 1. 连接数据库
    if (!db.open()) {
        qDebug() << "Error: Unable to open database!" << db.lastError().text();
        return res;
    }

    // 2. 查询数据
    QSqlQuery query;
    query.prepare("SELECT app_name, process_id1 FROM apps WHERE lb_index = :index");
    query.bindValue(":index", index);

    if (!query.exec()) {
        // qDebug() <<query.lastError().text();
        return res;
    }

    if (query.next()) {
        QString app_name = query.value("app_name").toString();
        int process_id1 = query.value("process_id1").toInt();

        // 此处处理查询到的进程
        res = checkProcessRunning(app_name, process_id1);
    }

    // 关闭数据库连接
    db.close();
    return res;
}

QString AppManager::queryAppNameByIndexFromDB(const int index)
{
    QString res = "AppName";
    // 1. 连接数据库
    if (!db.open()) {
        qDebug() << "Error: Unable to open database!" << db.lastError().text();
        return res;
    }

    // 2. 查询数据
    QSqlQuery query;
    query.prepare("SELECT app_name FROM apps WHERE lb_index = :index");
    query.bindValue(":index", index);

    if (!query.exec()) {
        qDebug() <<query.lastError().text();
        return res;
    }

    if (query.next()) {
        res = query.value("app_name").toString();
    }

    // 关闭数据库连接
    db.close();
    return res;
}

int AppManager::queryPID1ByIndexFromDB(const int index)
{
    int res = 0;
    // 1. 连接数据库
    if (!db.open()) {
        qDebug() << "Error: Unable to open database!" << db.lastError().text();
        return res;
    }

    // 2. 查询数据
    QSqlQuery query;
    query.prepare("SELECT process_id1 FROM apps WHERE lb_index = :index");
    query.bindValue(":index", index);

    if (!query.exec()) {
        qDebug() <<query.lastError().text();
        return res;
    }

    if (query.next()) {
        res = query.value("process_id1").toInt();
    }

    // 关闭数据库连接
    db.close();
    return res;
}

int AppManager::queryPID2ByIndexFromDB(const int index)
{
    int res = 0;
    // 1. 连接数据库
    if (!db.open()) {
        qDebug() << "Error: Unable to open database!" << db.lastError().text();
        return res;
    }

    // 2. 查询数据
    QSqlQuery query;
    query.prepare("SELECT process_id2 FROM apps WHERE lb_index = :index");
    query.bindValue(":index", index);

    if (!query.exec()) {
        qDebug() <<query.lastError().text();
        return res;
    }

    if (query.next()) {
        res = query.value("process_id2").toInt();
    }

    // 关闭数据库连接
    db.close();
    return res;
}

bool AppManager::isAppInDB(const int index)
{
    bool res = false;
    // 1. 连接数据库
    if (!db.open()) {
        qDebug() << "Error: Unable to open database!" << db.lastError().text();
        return res;
    }

    // 2. 查询数据
    QSqlQuery query;
    query.prepare("SELECT * FROM apps WHERE lb_index = :index");
    query.bindValue(":index", index);

    if (!query.exec()) {
        qDebug() <<query.lastError().text();
    }

    if (query.next()) {
        res = true;
    }

    // 关闭数据库连接
    db.close();
    return res;
}



BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
    DWORD pid;
    GetWindowThreadProcessId(hwnd, &pid);
    if (pid == lParam)  // 比较 PID 是否匹配
    {
        // 在此处处理找到的窗口句柄 hwnd
        WINDOWPLACEMENT wp;
        SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
        wp.length = sizeof(WINDOWPLACEMENT);
        bool bVisible = (GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE)!= 0;
        if(GetWindowPlacement(hwnd, &wp)) {
            if (wp.showCmd == SW_SHOWMAXIMIZED)
                    ShowWindow(hwnd, SW_SHOW);
            else {
                if(bVisible)
                    ShowWindow(hwnd, SW_RESTORE);
                else
                    ShowWindow(hwnd, SW_SHOW);
            }

        }
        // ShowWindow(hwnd, SW_SHOW);
        // ShowWindow(hwnd, SW_RESTORE);  // 显示窗口
        SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
        return false;  // 停止枚举
    }
    return true;  // 继续枚举
}


QString GetLinkTarget(const QString &lnkPath) {
    HRESULT hres;
    IShellLink* psl;
    WCHAR szGotPath[MAX_PATH];
    WIN32_FIND_DATA wfd;

    // 初始化 COM 库
    hres = CoInitialize(NULL);
    if (!SUCCEEDED(hres))
        return QString();

    // 获取 IShellLink 接口指针
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
    if (SUCCEEDED(hres)) {
        IPersistFile* ppf;

        // 获取 IPersistFile 接口指针
        hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
        if (SUCCEEDED(hres)) {
            // 加载快捷方式文件
            hres = ppf->Load((LPCWSTR)lnkPath.utf16(), STGM_READ);
            if (SUCCEEDED(hres)) {
                // 解析快捷方式路径
                hres = psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY);
                if (SUCCEEDED(hres)) {
                    // 检查是否被错误地重定向到 Program Files (x86)
                    QString targetPath = QString::fromWCharArray(szGotPath);
                    if (!targetPath.contains("Program Files (x86)")) {
                        // 手动替换为 Program Files
                        targetPath.replace("Program Files (x86)", "Program Files");
                    }
                    ppf->Release();
                    psl->Release();
                    CoUninitialize();
                    return targetPath;
                }
            }
            ppf->Release();
        }
        psl->Release();
    }
    CoUninitialize();
    return QString();
}



QString convertWindowsToLinuxPath(const QString &windowsPath) {
    // 替换反斜杠为正斜杠
    QString linuxPath = windowsPath;
    linuxPath.replace('\\', '/');

    // 可以选择删除多余的连续正斜杠
    // linuxPath = linuxPath.remove("//");

    return linuxPath;
}





